﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Kostas.K_Lib;
using Kostas.K_Lib.IO;

[assembly: AssemblyVersion("1.0.1.0")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyTitle("K-Tree")]
[assembly: AssemblyDescription("Calculates the size of the folder and all subfolders recursively and outputs starting with biggest. Very fast. Useful for quickly finding out what's taking the space on your disk.")]
[assembly: AssemblyCompany("K-Utils")]
[assembly: AssemblyProduct("K-Tree")]
[assembly: AssemblyCopyright("K-Utils 2008, 2009")]
[assembly: AssemblyTrademark("K-Tree")]

namespace K_Utils.K_Tree
{
	class Program
	{
		private static long minSize = 0;

		private static bool waitKey;

		private static void Exit()
		{
			if (waitKey)
			{
				Console.Write("Press any key...");
				Console.ReadKey();
			}
			return;
		}

		private static void Help()
		{
			Console.WriteLine();
			Console.WriteLine("Usage: k-tree path [options]");
			Console.WriteLine(@"Example: k-tree c:\ -w -v Verbose -min 10M");
			Console.WriteLine();
			Console.WriteLine("Options:");
			Console.WriteLine();
			Console.WriteLine("-?: Display help");
			Console.WriteLine("-h: Display help");
			Console.WriteLine("-w: Don't exit until key is pressed");
			Console.WriteLine("-v <verbosity>: verbosity level, one of [ Silent | Normal | Verbose ]");
			Console.WriteLine("-min <size>: display only if bigger than <size>[K|M]");
			Console.WriteLine();
			Console.WriteLine("Use suffix 'K' for kilobytes, 'M' for megabytes, no prefix for bytes");
			Console.WriteLine();
			Exit();
		}

		private static bool BigEnough(K_Directory directory)
		{
			return directory.FullSize > minSize;
		}

		private static void Main(string[] args)
		{
			List<string> argList = new List<string>(args);

			// init switches

			waitKey = argList.Contains("-w");
			bool helpKey = argList.Contains("-h") || argList.Contains("-?");

			if (helpKey || argList.Count < 1)
			{
				Help();
				return;
			}

			string path = args[0];

			int verbosityIndex = argList.IndexOf("-v");
			if (verbosityIndex == -1)
				K_Lib.Verbosity = Verbosity.Normal;
			else try
				{
					K_Lib.Verbosity = (Verbosity)Enum.Parse(typeof(Verbosity), argList[verbosityIndex + 1]);
				}
				catch
				{
					Console.WriteLine();
					Console.WriteLine("Error: -v switch should be followed by one of [Silent|Normal|Verbose]");
					Help();
					return;
				}

			int minSizeIndex = argList.IndexOf("-min");
			if (minSizeIndex >= 0)
				try
				{
					string sizeStr = argList[minSizeIndex + 1];
					char cUnit = sizeStr[sizeStr.Length - 1];
					int iUnit = 1;
					if (cUnit == 'K' || cUnit == 'k')
					{
						iUnit = 1024;
						sizeStr = sizeStr.Remove(sizeStr.Length - 1);
					}
					else if (cUnit == 'M' || cUnit == 'm')
					{
						iUnit = 1024 * 1024;
						sizeStr = sizeStr.Remove(sizeStr.Length - 1);
					}
					minSize = int.Parse(sizeStr) * iUnit;
				}
				catch
				{
					Console.WriteLine();
					Console.WriteLine("Error: -min switch should be followed by number");
					Help();
					return;
				}

			if (!Directory.Exists(path))
			{
				Console.WriteLine("ERROR: Directory \"{0}\" does not exist", path);
				Help();
				return;
			}
			K_Directory directory = new K_Directory(path);
			List<K_Directory> list = directory.Children.FindAll(BigEnough);
			list.Sort();
			foreach (K_Directory subDirectory in list)
			{
				const int KILO = 1024;
				const int MEGA = 1024 * 1024;
				if (subDirectory.FullSize > 10 * MEGA)
					Console.WriteLine("{0,8:N0} MB {1}", subDirectory.FullSize / MEGA, subDirectory.Info.FullName);
				else if (subDirectory.FullSize > 10 * KILO)
					Console.WriteLine("{0,8:N0} KB {1}", subDirectory.FullSize / KILO, subDirectory.Info.FullName);
				else
					Console.WriteLine("{0,8:N0} bytes {1}", subDirectory.FullSize, subDirectory.Info.FullName);
			}

			if (waitKey)
			{
				Console.Write("Press any key...");
				Console.ReadKey();
			}
		}
	}
}
